package com.data.security.rodrigo;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import com.data.security.modelo.Archivo;
import com.data.security.modelo.Preferencias;
import com.data.security.modelo.sebastian.ShaCrypt;

import android.content.Context;
import android.os.PowerManager;

public class Encripta {
	
	//Objeto Singleton
	private static Encripta encripta;
	
	/**
	 * Obtiene la instancia de la actual objeto.
	 * @return
	 */
	public static Encripta getEncripta(){
		if(encripta==null){
			encripta=new Encripta();
		}
		return encripta;
	}

	/**
	 * Constructor
	 */
	private Encripta(){
		
	}
	

	/**
	 * Realiza el proceso de cifrar el archivo.
	 * @param archivo -> Objeto archivo a encriptar.
	 * @param contexto -> El contexto del aplicativo se usa para llamar el power manager del dispositivo
	 * y no permitir que el este entre en estado de inactividad en caso de realizar un proceso de cifrado muy largo.
	 * @return -> True si realiza el cifrado correctamente o false en caso contrario.
	 */
	public boolean encriptar(Archivo archivo, Context contexto) {
		boolean respuesta = false;
		PowerManager pm = (PowerManager) contexto
				.getSystemService(Context.POWER_SERVICE);
		@SuppressWarnings("deprecation")
		PowerManager.WakeLock wl = pm.newWakeLock(
				PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Encriptando...");
		wl.acquire();
		String ll = Preferencias.getLlave(contexto);
		SecretKeySpec key = new SecretKeySpec(ShaCrypt.generarArreglo(
				ll.getBytes(), ShaCrypt.SHA256), "AES");
		Cipher cipher;
		try {
			cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, key);
			archivo.setData(cipher.doFinal(archivo.getData()));
			archivo.setTamanio(archivo.getData().length);
			wl.release();
			respuesta = true;
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			wl.release();

		} catch (IllegalBlockSizeException e) {

			e.printStackTrace();
			wl.release();

		} catch (BadPaddingException e) {

			e.printStackTrace();
			wl.release();

		} catch (NoSuchAlgorithmException e) {

			e.printStackTrace();
			wl.release();

		} catch (NoSuchPaddingException e) {

			e.printStackTrace();
			wl.release();

		} catch (OutOfMemoryError e) {
			e.printStackTrace();
			wl.release();

		}

		return respuesta;

	}

	/**
	 * Realiza el proceso de descifrar el archivo.
	 * @param archivo -> Objeto archivo a descifrar.
	 * @param contexto -> El contexto del aplicativo se usa para llamar el power manager del dispositivo
	 * y no permitir que el este entre en estado de inactividad en caso de realizar un proceso de descifrado muy largo.
	 * @return -> True si realiza esi desencripta correctamente o false en caso contrario.
	 */
	public boolean descifrar(Archivo data, Context contexto) {
		boolean respuesta = false;
		PowerManager pm = (PowerManager) contexto
				.getSystemService(Context.POWER_SERVICE);
		@SuppressWarnings("deprecation")
		PowerManager.WakeLock wl = pm.newWakeLock(
				PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Desencriptando...");
		wl.acquire();
		String ll = Preferencias.getLlave(contexto);
		SecretKeySpec key = new SecretKeySpec(ShaCrypt.generarArreglo(ll.getBytes(), ShaCrypt.SHA256), "AES");
		Cipher cipher;
		try {

			cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.DECRYPT_MODE, key);
			data.setData(cipher.doFinal(data.getData()));
			data.setTamanio(data.getData().length);
			wl.release();
			respuesta = true;

		} catch (InvalidKeyException e) {
			e.printStackTrace();
			wl.release();

		} catch (IllegalBlockSizeException e) {

			e.printStackTrace();
			wl.release();

		} catch (BadPaddingException e) {

			e.printStackTrace();
			wl.release();

		} catch (NoSuchAlgorithmException e) {

			e.printStackTrace();
			wl.release();

		} catch (NoSuchPaddingException e) {

			e.printStackTrace();
			wl.release();

		} catch (OutOfMemoryError e) {
			e.printStackTrace();
			wl.release();

		}

		return respuesta;
	}

}
